<div class="container w1100 clearfloat">
  <div class="column mainCol l">
    <div id="content1" class="content">
        <h2 class="title">3个JavaScript装逼技巧</h2>
        <h2 class="subtitle">空（null、undefined）验证</h2>
        <p class="detialInfo">当我们创建了一个新的变量，我们通常会去验证该变量的值是否为空（null）或未定义（undefined），如果直接写则如下所示：</p>
        <pre><code class="javascript">if(variable1 !== null || variable1 !== undefined || variable1 !== '')<br>{<br>&nbsp;let variable2 = variable1<br>}</code></pre>
        <p class="detialInfo">可以使用更简洁的版本：</p>
        <pre><code class="javascript">let = variable2 = variable1 || '';</code></pre>
        <p class="detialInfo">逻辑与：expr1&&expr2——如果expr1能转换成false则返回expr1，否则返回expr2。在Boolean环境中使用时，两个操作结果都为true时返回true，否则返回false。</p>
        <p class="detialInfo">逻辑或：expr1||expr2——如果expr1能转换成true则返回expr1，否则返回expr2。在Boolean环境中使用时，两个操作结果中只要有一个为true时返回true，二者操作结果都为false时，返回false。</p>
        <h2 class="subtitle">数组</h2>
        <p class="detialInfo">非优化代码:</p>
        <pre><code class="javascript">let a = new Array();<br>a[0] = 'myString1';<br>a[1] = 'myString2';<br>a[2] = 'myString3';<br></code></pre>
        <p class="detialInfo">优化代码:</p>
        <pre><code class="javascript">let a = ['myString1','myString2','myString3'];</code></pre>
        <h2 class="subtitle">if true .. else 的优化</h2>
        <pre><code class="javascript">let big;<br>if(x>10){<br>&nbsp;big = true;<br>}else{<br>&nbsp;big = false<br>}</code></pre>
        <p class="detialInfo">简化后：</p>
        <pre><code class="javascript">let big = x > 10? true:false;</code></pre>
    </div>
    <div id="content2" class="content">
        <h2 class="title">深入详解函数的柯里化</h2>
        <h2 class="subtitle">补充知识点之函数的隐式转换</h2>
        <pre><code class="javascript">/*第一种情况：*/<br>function fn(){return 20;}<br>console.log(fn + 10);/*function fn()return 20;}10*/<br><br>/*第二种情况：*/<br>function fn(){return 20;}<br>fn.toString = function(){return 10;}<br>console.log(fn + 10);/*20*/<br><br>/*第三种情况：*/<br>function fn(){return 20;}<br>fn.toString = function(){return 10;}<br>fn.valueOf = function(){return 5;}<br>console.log(fn + 10);/*15*/</code></pre>
        <p class="detialInfo">从上面的例子中我们得出关于函数隐式转换的结论——当我们没有重新定义toString与valueOf时，函数的隐式转换会调用默认的toString方法，他会将函数的定义内容作为字符串返回，而当我们主动定义了toString/vauleOf方法时，那么隐式转换的返回结果就由我们自己控制，其中valueOf会比toString后执行。</p>
        <h2 class="subtitle">补充知识点之利用call/apply封装数组的map方法</h2>
        <p class="detialInfo">map()——对数组中的每一项运行给定的函数，返回每次函数调用的结果组成的数组。</p> 
        <pre><code class="javascript">/*回调函数中有三个参数，第一个表示newArr的每一项，第二个参数表示该项在数组中的索引值，第三个表示数组本身。<br>回调函数中的this，当map不存在第二参数时，this指向丢失，当存在第二个参数时，指向该参数所设定的对象。*/<br><br>var newArr = [1,2,3,4].map(function(item,i,arr)<br>{<br>&nbsp;console.log(item,i,arr,this);<br>&nbsp;return item + 1;<br>},{a:1});<br><br>console.log(newArr);/*[2,3,4,5]*/</code></pre> 
        <p class="detialInfo">封装map函数如下：</p> 
        <pre><code class="javascript">Array.prototype._map = function(fn,context)<br>{<br>&nbsp;var temp = [];<br>&nbsp;if(typeof fn == 'function')<br>&nbsp;{<br>&nbsp;&nbsp;var k = 0, len = this.length;<br>&nbsp;&nbsp;for(; k < len; k++)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;temp.push(fn.call(context,this[k],k,this));<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp;console.error('TypeError:'+fn+'is not a function.');<br>&nbsp;}<br>&nbsp;return temp;<br>}<br><br>var newArr = [1,2,3,4]._map(function(item)<br>{<br>&nbsp;return item + 1;<br>});/*[2,3,4,5]*/</code></pre> 
        <h2 class="subtitle">由浅入深的柯里化</h2>
        <p class="detialInfo">实现一个add方法，使计算结果能够满足如下预期：</p> 
        <pre><code class="javascript">add(1)(2)(3) = 6<br>add(1, 2, 3)(4) = 10<br>add(1)(2)(3)(4)(5) = 15</code></pre>
        <p class="detialInfo">计算结果正是所有参数的和，add方法每运行一次，肯定返回了一个同样的函数，继续计算剩下的参数。当我们只调用两次时，可以这样封装：</p> 
        <pre><code class="javascript">function add(a){<br>&nbsp;return function(b){<br>&nbsp;&nbsp;return a + b;<br>&nbsp;}<br>}<br><br>console.log(add(1)(2));</code></pre>
        <p class="detialInfo">调用多次，则一次类推。总结上面的例子，是利用闭包的特性，将所有的参数，集中到最后返回的函数里进行计算并返回结果，因此我们封装的主要目的是将参数集中起来计算，如下：</p> 
        <pre><code class="javascript">function add(){<br>&nbsp;var _args = [].slice.call(arguments);/*第一次执行时，定义一个数组专门用来存储所有的参数*/<br>&nbsp;var adder = function(){<br>&nbsp;&nbsp;var _adder = function(){<br>&nbsp;&nbsp;&nbsp;[].push.apply(_args,[].slice.call(arguments));<br>&nbsp;&nbsp;&nbsp;return _adder;<br>&nbsp;&nbsp;};<br>&nbsp;&nbsp;_adder.toString = function(){<br>&nbsp;&nbsp;&nbsp;return _args.reduce(function(){return (a,b);});<br>&nbsp;&nbsp;}/*利用隐式转换的特性，当最后执行隐式转换时，并计算最终的值返回*/<br>&nbsp;&nbsp;return _adder;<br>&nbsp;}/*在内部声明一个函数，利用闭包的特性保存_args并收集所有的参数值*/<br>&nbsp;return adder.apply(null,[].slice.call(arguments));<br>}<br><br>console.log(add(1, 2, 3, 4, 5));<br>console.log(add(1, 2, 3, 4)(5));<br>console.log(add(1)(2)(3)(4)(5)); <br></code></pre>
        <p class="detialInfo">柯里化——又称部分求值，是把接受多个参数的函数变换成接受一个单一参数（最初函数的第一个参数）的函数，并且返回一个新的函数的技术，新函数接受余下参数并返回运算结果。</p>
        <h2 class="subtitle">柯里化通用式</h2>
        <pre><code class="javascript">var currying = function(fn){<br>&nbsp;var args = [].slice.call(arguments,l);<br>&nbsp;return function(){<br>&nbsp;&nbsp;/*主要还是收集所有需要的参数到一个数组中，便于统一计算*/<br>&nbsp;&nbsp;var _args = args.concat([].slice.call(arguments));<br>&nbsp;&nbsp;return fn.apply(null,_args);<br>&nbsp;}<br>}<br><br>var sum = currying(function(){<br>&nbsp;var args = [].slice.call(arguments);<br>&nbsp;return args.reduce(function(a,b){<br>&nbsp;&nbsp;return a + b;<br>&nbsp;})<br>},10);<br><br>console.log(sum(20,10));/*40*/<br>console.log(sum(10,5));/*25*/</code></pre>
        <h2 class="subtitle">柯里化与bind</h2>
        <pre><code class="javascript">Object.prototype.bind = function(context){<br>&nbsp;var _this = this;<br>&nbsp;var args = [].slice.call(arguments,1);<br>&nbsp;return function(){<br>&nbsp;&nbsp;return _this.apply(context,args);<br>&nbsp;}<br>}</code></pre>
    </div>
  </div>
  <div class="column sideCol l">
    <ul class="title-list">
      <li><a class="link" href="#content1">3个JavaScript装逼技巧</a></li>
      <li><a class="link" href="#content2">深入详解函数的柯里化</a></li>
    </ul>
  </div>
</div>
